//
//  GetRequestHelper.swift
//  kz
//
//  Created by Tech_001 on 3/8/2017.
//  Copyright © 2017 Tech_001. All rights reserved.
//

import Foundation
import UIKit
import SystemConfiguration
import SwiftyJSON

class RequestHelper{
    static let requestScheme = "https"
    static var noNetworkDialog: UIAlertController?
    static let tokenParam = ["token" : "Qgx2kCCHz43lnQZmUDjejnm41RoNzpMEaOMbBrod"]
    
    static func get(atPath requestPath: String, withCompletion callback: @escaping (_ data: Data) throws -> Void = {_ in }, withError errorCallback: @escaping (_ error: Error) -> Void = {_ in }){
        if let domain = UserDefaults.standard.value(forKey: DefaultKey.USER_DOMAIN){
            let domainScheme = UserDefaults.standard.string(forKey: DefaultKey.DOMAIN_SCHEME)!
            
            if let url = URL(string: "\(domainScheme)://\(domain)\(requestPath)") {
                print("地址：\(url)")
                self.request(url, method: "GET", withData: nil, withCompletion: callback, withError: errorCallback)
            }
        }
    }
    
    
    
    static func get(_ domain: String, atPath requestPath: String, withCompletion callback: @escaping (_ data: Data) throws -> Void = {_ in }, withError errorCallback: @escaping (_ error: Error) -> Void = {_ in }){
        
        var url = URL(string: "\(domain)\(requestPath)")!
        
        if url.scheme == nil {
            url = URL(string: "\(self.requestScheme)://\(domain)\(requestPath)")!
        }
        
        self.get(url, withCompletion: callback, withError: errorCallback)
    }
    
    
    
    static func get(_ url: URL, withCompletion callback: @escaping (_ data: Data) throws -> Void = {_ in }, withError errorCallback: @escaping (_ error: Error) -> Void = {_ in }, ignoreCache: Bool = false){
        var mUrl : URL?
        mUrl = url
        
        if mUrl?.scheme == nil {
            mUrl = URL(string: "\(self.requestScheme)://\(url.host!)\(url.path)")!
        }
        
        self.request(mUrl!, method: "GET", withData: nil, withCompletion: callback, withError: errorCallback, ignoreCache: ignoreCache)
    }
    
    
    
    static func post(atPath requestPath: String, withData: Dictionary<String, String>, withCompletion callback: @escaping (_ data: Data) throws -> Void = {_ in }, withError errorCallback: @escaping (_ error: Error) -> Void = {_ in }){
        if let domain = UserDefaults.standard.value(forKey: DefaultKey.USER_DOMAIN){
            let domainScheme = UserDefaults.standard.string(forKey: DefaultKey.DOMAIN_SCHEME)!
            
            if var url = URL(string: "\(domainScheme)://\(domain)\(requestPath)") {
                print("地址:\(url)")
                self.request(url, method: "POST", withData: withData, withCompletion: callback, withError: errorCallback)
            }
        }
    }
    
    
    
    static func request(_ url: URL, method: String, withData: [String:String]?, withCompletion callback: @escaping (_ data: Data) throws -> Void = {_ in }, withError errorCallback: @escaping (_ error: Error) -> Void = {_ in }, ignoreCache: Bool = false){
        
        if self.isInternetAvailable() == false {
            if let dialog = self.noNetworkDialog {
                
            }else{
            }
        }
        
        if url.scheme != nil && url.host != nil {
            var url = url
            
            var withData = withData
            if  url.host! == UserDefaults.standard.string(forKey: DefaultKey.USER_DOMAIN)! && url.path.contains("/clientsAPIs/") || url.path.contains("/ClientsAPIs/") {
                withData?["token"] = "Qgx2kCCHz43lnQZmUDjejnm41RoNzpMEaOMbBrod"
                
                if url.query == nil {
                    url = URL(string: "\(url.scheme!)://\(url.host!)/\(url.path)/?\(self.convertTokenParams())")!
                }else{
                    url = URL(string: "\(url.scheme!)://\(url.host!)/\(url.path)/?\(url.query!)&\(self.convertTokenParams())")!
                }
                print(url.absoluteString)
            }
            
            let path = url.path
            print("Scheme: \(String(describing: url.scheme!))")
            print("Host: \(String(describing: url.host!))")
            print("Path: \(url.path)")
            print("Query: \(url.query)")
            
            if withData != nil {
                print("Post data: \(self.convertGetParams(withData!))")
            }
            print("\n\n")
            
            var request: URLRequest
            if ignoreCache {
                request = URLRequest(url: url, cachePolicy:.reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 20)
            }else{
                
                if url.path == "/iVersion-manually.json"{
                    request = URLRequest(url: url, cachePolicy:.reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 20)
                }else{
                    request = URLRequest(url: url)
                }
                
            }
            
            request.httpMethod = method
            request.httpShouldHandleCookies = true
            let nsObject = Bundle.main.infoDictionary?["CFBundleShortVersionString"]
            let version = nsObject as! NSString
            request.setValue("ManbetX iOS", forHTTPHeaderField: "User-Agent")
            
            if withData != nil {
                request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
                request.httpBody = self.convertGetParams(withData!).data(using: String.Encoding.utf8)
            }
            
            let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
                if let httpResponse = response as? HTTPURLResponse {
                    let statusCode  = "\(httpResponse.statusCode)"
                    
                    let jsonData =  JSON(data ?? Data())
                    var code = "\(jsonData["c"].int ?? -1)"
                    var info = "无"
                    if code != "-1" && code != "0"{
                        info = CodeMessageHelper.get(code)
                    }
                    if code == "-1"{
                        code = "无"
                    }
                    if statusCode == "200" && code != "0" && code != "无"{
                        ToolHelper.statisticsPageWithInterface(pageName: url.path, statusCode: statusCode, kzingStatusCode: code, errorResponse: info)
                    }else if statusCode != "200"{
                        ToolHelper.statisticsPageWithInterface(pageName: url.path, statusCode: statusCode, kzingStatusCode: "无", errorResponse: "无")
                    }
                    
                }
                
                guard let data = data, error == nil else {                                                 // check for fundamental networking error
                    print("error=\(String(describing: error))")
                    if !checkGameJson(path, withCompletion: callback){
                        errorCallback(error!)
                    }
                    return
                }
                  print("头信息：\(request.allHTTPHeaderFields ?? [:])")
                if let httpResponse = response as? HTTPURLResponse {
                    if httpResponse.statusCode != 200 {           // check for http errors
                        print("\(request.url!.absoluteString) statusCode should be 200, but is \(httpResponse.statusCode)")
                        
                        if httpResponse.statusCode == 404 && path == "/clientsAPIs/getInfo" {
                            do{
                                try callback(data)
                            }catch{
                                let customError = NSError(domain: url.host!, code:httpResponse.statusCode, userInfo:nil)
                                errorCallback(customError)
                            }
                            return
                        }
                        //为了game.json 有个提示
                        let currentViewController = UIViewController.current()
                        let currntViewConrollerString  = NSStringFromClass((currentViewController?.classForCoder ?? nil)!)
                        print("所在控制器\(currntViewConrollerString)")
                        if(path=="/game_new.json"){
                            if(currntViewConrollerString == "d11.NewHomeVC"||currntViewConrollerString=="d11.GameListVC"||currntViewConrollerString=="d11.HelperListVC"){
                                let customError = NSError(domain: url.host!, code:httpResponse.statusCode, userInfo:nil)
                                errorCallback(customError)
                                return
                            }
                        }
                        
                        if httpResponse.statusCode == 403 && UserHelper.getLoginStatus() {
                            DispatchQueue.main.async {
                                if let topController = UIHelper.getTopController() {
                                    if topController is LaunchViewController {
                                        return
                                    }
//                                    LoginViewController.loginIfNeedController(currentController: self) {}
                                }
                            }
                            return
                        }
                        
                        let customError = NSError(domain: url.host!, code:httpResponse.statusCode, userInfo:nil)
                        if !checkGameJson(path, withCompletion: callback){
                            errorCallback(customError)
                        }
                        return
                    }
                }
                
                //Http Response 200
                do{
                    if path == "/game_new.json" {
                        UserDefaults.standard.set(data, forKey: DefaultKey.DEFAULT_GAME_JSON)
                        //                        checkGameJson(path, withCompletion: callback)
                        //                        return
                    }
                    try callback(data)
                }catch{
                    let customError = NSError(domain: url.host!, code:200, userInfo:nil)
                    
                    if !checkGameJson(path, withCompletion: callback){
                        errorCallback(customError)
                    }
                }
            }
            task.resume()
        }
    }
    
    
    
    
    private static func checkGameJson(_ path: String, withCompletion callback: @escaping (_ data: Data) throws -> Void) -> Bool {
        if path == "/game_new.json" {
            do{
                try callback(GlobalInfo.getDefaultJson())
                
                return true
            }catch{
                return false
            }
        }
        return false
    }
    
    
    
    static func convertTokenParams() -> String{
        return self.convertGetParams(tokenParam)
    }
    
    
    static func getJSONStringFromDictionary(dictionary:NSDictionary) -> NSString {
        if (!JSONSerialization.isValidJSONObject(dictionary)) {
            print("无法解析出JSONString")
            return ""
        }
        let data : NSData! = try? JSONSerialization.data(withJSONObject: dictionary, options: []) as NSData?
        let JSONString = NSString(data:data as Data,encoding: String.Encoding.utf8.rawValue)
        return JSONString!
    }
    
    
    
    static func convertGetParams(_ params: [String:String], connector: String = "&") -> String {
        var firstOneAdded = false
        var contentBodyAsString: String = ""
        let contentKeys:Array<String> = Array(params.keys)
        for contentKey in contentKeys {
            if(!firstOneAdded) {
                contentBodyAsString += contentKey + "=" + params[contentKey]!
                firstOneAdded = true
            }
            else {
                contentBodyAsString += connector + contentKey + "=" + params[contentKey]!
            }
        }
        contentBodyAsString = contentBodyAsString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
        //   contentBodyAsString = contentBodyAsString.addingPercentEscapes(using: String.Encoding.utf8)!
        contentBodyAsString = contentBodyAsString.replacingOccurrences(of: "+", with: "%2B")
        
        return contentBodyAsString
    }
    
    
    
    static func isInternetAvailable() -> Bool{
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)
        
        let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }
        
        var flags = SCNetworkReachabilityFlags()
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
            return false
        }
        let isReachable = flags.contains(.reachable)
        let needsConnection = flags.contains(.connectionRequired)
        return (isReachable && !needsConnection)
    }
    
    
    /**  Cookie Related   **/
    static func makeCFCookie(_ forPath: String = "/"){
        if let domain = UserDefaults.standard.string(forKey: DefaultKey.USER_DOMAIN) {
            var array: [String] = domain.components(separatedBy: ".")
            
            let cfCookieDomain: String = ".\(array[array.count - 2]).\(array[array.count - 1])"
            let calendar = Calendar.current
            let expires = Date(timeIntervalSinceNow: 0)
            let date = calendar.date(byAdding: .minute, value: 60, to: expires)
            
            var properties = [HTTPCookiePropertyKey: Any](minimumCapacity: 5)
            properties[HTTPCookiePropertyKey.name] = "cf"
            properties[HTTPCookiePropertyKey.value] = "1"
            properties[HTTPCookiePropertyKey.domain] = cfCookieDomain
            properties[HTTPCookiePropertyKey.expires] = date
            properties[HTTPCookiePropertyKey.path] = "/"
            
            if let cookie = HTTPCookie.init(properties: properties) {
                HTTPCookieStorage.shared.setCookie(cookie)
                print("!!!---cookie222:\(cookie)");
            }
        }
    }
    
    
    static func addTokenCookies(){
        let url = UserDefaults.standard.string(forKey: DefaultKey.USER_DOMAIN)
        print("=====addToken:\(url)")
        if let domain = UserDefaults.standard.string(forKey: DefaultKey.USER_DOMAIN) {
            let calendar = Calendar.current
            let expires = Date(timeIntervalSinceNow: 0)
            let date = calendar.date(byAdding: .minute, value: 60, to: expires)
            
            var properties:[HTTPCookiePropertyKey: Any] = [:]
            if(isTest){
                properties[HTTPCookiePropertyKey.name] = DefaultKey.CCTOKEN81
                properties[HTTPCookiePropertyKey.value] = UserDefaults.standard.object(forKey: DefaultKey.CCTOKEN81) as? String ?? ""
            }else{
                properties[HTTPCookiePropertyKey.name] = DefaultKey.CCTOKEN11
                properties[HTTPCookiePropertyKey.value] = UserDefaults.standard.object(forKey: DefaultKey.CCTOKEN11) as? String ?? ""
            }
            
            properties[HTTPCookiePropertyKey.domain] = domain
            properties[HTTPCookiePropertyKey.expires] = date
            properties[HTTPCookiePropertyKey.path] = "/"
            if let cookie = HTTPCookie.init(properties: properties) {
                HTTPCookieStorage.shared.setCookie(cookie)
                print("!!!---cookie:\(cookie)");
            }
            
            var properties2:[HTTPCookiePropertyKey: Any] = [:]
            
            if(isTest){
                properties2[HTTPCookiePropertyKey.name] = DefaultKey.VCTOKEN81
                properties2[HTTPCookiePropertyKey.value] = UserDefaults.standard.object(forKey: DefaultKey.VCTOKEN81) as? String ?? ""
            }else{
                properties2[HTTPCookiePropertyKey.name] = DefaultKey.VCTOKEN11
                properties2[HTTPCookiePropertyKey.value] = UserDefaults.standard.object(forKey: DefaultKey.VCTOKEN11) as? String ?? ""
            }
            properties2[HTTPCookiePropertyKey.domain] = domain
            properties2[HTTPCookiePropertyKey.expires] = date
            properties2[HTTPCookiePropertyKey.path] = "/"
            if let cookie2 = HTTPCookie.init(properties: properties2) {
                HTTPCookieStorage.shared.setCookie(cookie2)
                print("!!!---cookie:\(cookie2)");
            }
        }
    }
    
    
    static func makeGameDomainCookie(){
        let GAME_DOMAIN_LIST = [".mightypanda88.com", ".mp176588.com", ".kzonlinegame.com", "msb-kzing.prdasbbwla1.com", ".uv128.com", ".goldenphoenix88.com", ".dragonfish88.com"]
        
        for cookie: HTTPCookie in HTTPCookieStorage.shared.cookies! {
            if(isTest){
                if cookie.name == DefaultKey.CCTOKEN81{
                    UserDefaults.standard.set(cookie.value, forKey: DefaultKey.CCTOKEN81)
                }
                if cookie.name ==  DefaultKey.VCTOKEN81{
                    UserDefaults.standard.set(cookie.value, forKey: DefaultKey.VCTOKEN81)
                }
            }else{
                if cookie.name == DefaultKey.CCTOKEN11{
                    UserDefaults.standard.set(cookie.value, forKey: DefaultKey.CCTOKEN11)
                }
                if cookie.name ==  DefaultKey.VCTOKEN11{
                    UserDefaults.standard.set(cookie.value, forKey: DefaultKey.VCTOKEN11)
                }
            }
            
            
            for GAME_DOMAIN: String in GAME_DOMAIN_LIST {
                var properties = [HTTPCookiePropertyKey: Any](minimumCapacity: 5)
                properties[HTTPCookiePropertyKey.value] = cookie.value
                properties[HTTPCookiePropertyKey.name] = cookie.name
                properties[HTTPCookiePropertyKey.domain] = GAME_DOMAIN
                properties[HTTPCookiePropertyKey.expires] = cookie.expiresDate
                properties[HTTPCookiePropertyKey.path] = "/"
                
                if let cookie = HTTPCookie.init(properties: properties) {
//                    print("!!!---cookie:\(cookie)")
                    HTTPCookieStorage.shared.setCookie(cookie)
                }
            }
        }
    }
    
    
    // 删除默认 Cookie
    static func deleteDefaultCookie(){
        let cookieStorage = HTTPCookieStorage.shared
        for cookie in cookieStorage.cookies! {
            cookieStorage.deleteCookie(cookie)
        }
    }
}


extension UIViewController {
    class func current(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController {
            return current(base: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            return current(base: tab.selectedViewController)
        }
        if let presented = base?.presentedViewController {
            return current(base: presented)
        }
        return base
    }
}
